<?php

/**
 * 判断用户是否登录
 *
 * @return boolean
 */
function is_loggedin() {
  //global $user;
  //print_r($user);
  if ($_SESSION['id'] > 0)
    return true;
  return false;
}

/**
 * 判断用户是否登录
 *
 * @return boolean
 */
function is_logined() {
  //global $user;
  //print_r($user);
  if ($_SESSION['user_id'] > 0)
    return true;
  return false;
}

/**
 * 高级if
 *
 * @param unknown_type $expression
 * @param unknown_type $true
 * @param unknown_type $false
 * @return unknown
 */
function iif($expression, $true, $false = '') {
  if ($expression == 0) {
    return $false;
  } else {
    return $true;
  }
}

/**
 * 切开字符串
 *
 * @param unknown_type $string
 * @param unknown_type $length
 * @return unknown
 */
function cut_string($string, $length) {
  $len = strlen($string);

  if ($len > $length) {
    $part_len = round(($length - 5) / 4);
    $string = substr($string, 0, $part_len * 3)." ... ".substr($string, -$part_len, $part_len);
  }

  return $string;
}

/**

 */
function cache_header($expires = 900) {
  @header('Last-Modified: '.@gmdate("D, d M Y H:i:s", floor(@time() / $expires) * $expires).' GMT');
  @header('Cache-Control: max-age='.$expires.', must-revalidate');
  @header('Expires: '.@gmdate("D, d M Y H:i:s", @time() + $expires).' GMT');
}

function no_cache_header() {
  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  header("Pragma: no-cache");
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
}

/**
 * 比较时间
 *
 * @param unknown_type $t
 * @param unknown_type $format
 * @return unknown
 */
function get_diff_date($time, $format = "") {
  $now = time();

  if ($time + 86400 > $now) {
    return "Today";
  } else if ($time + 172800 > $now) {
    return "Yesterday";
  }

  if ($format == "") {
    $format = _CONST_DATE_FORMAT;
  }

  return date($format, $time + _CONST_TIME_OFFSET * 3600);
}

function convert_date($time, $format = "") {
  if ($format == "") {
    $format = _CONST_DATE_FORMAT." "._CONST_TIME_FORMAT;
  }

  if ($time)
    return @date($format, $time + _CONST_TIME_OFFSET * 3600);
  else
    return "n/a";
}

/**
 * 把字符串换成mysql形式
 */
function string_sql($string) {
    if ($string == "" and $string != 0) {
        return 'NULL';
    } else {
        return "'".addslashes($string)."'";
    }
}

/**
 * 把string换成file形式 引号前加\
 */
function string_file($string) {
  return str_replace("\"", "\\\"", $string);
}

/**
 * 设置cookies
 *
 * @param unknown_type $name
 * @param unknown_type $value
 * @param unknown_type $expire
 */
function set_cookie($name, $value = "", $expire = 0) {
  if (_CONST_COOKIE_DOMAIN && _CONST_COOKIE_SECURE) {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH, _CONST_COOKIE_DOMAIN, _CONST_COOKIE_SECURE);
  } else if (_CONST_COOKIE_DOMAIN) {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH, _CONST_COOKIE_DOMAIN);
  } else {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH);
  }
}

function is_checked($check) { return iif($check, 'checked="checked"'); }
function is_selected($check) { return iif($check, 'selected="selected"'); }

/**
 * 计算字节数
 *
 * @param unknown_type $size
 * @return unknown
 */
function file_size($size) {
  if ($size > 1024*1024) {
    return sprintf("%01.2f MB", ($size/1024)/1024);
  } else if ($size > 1024) {
    return sprintf("%01.2f KB", $size/1024);
  } else {
    return $size." Bytes";
  }
}

/**
 * 页面跳转
 */
function redirect($message) {
  ?>
  <html>
  <head>
  <meta charset="UTF-8">
  <title>跳转</title>
  <meta http-equiv="Refresh" content="1;url=<?= $_REQUEST['referrer'] ?>" />
  </head>
  <body>
  <h2>跳转中...</h2>
  <p><?= $message ?></p>
  <p><a>如果浏览器不能自动跳转请点击这里.</a></p>
  </body>
  </html>
  <?
  exit();
}

/**
 * 页面跳转
 */
function error($errorcode, $message) {
  global $database;
  switch ($errorcode) {
    case 403:
      include_once(_CONST_LOCAL_LAYOUT_PATH."403.php");
      break;
    case 404:
    default:
      include_once(_CONST_LOCAL_LAYOUT_PATH."404.php");
  case 200:
      include_once(_CONST_LOCAL_LAYOUT_PATH."200.php");
      break;
  }
  exit();
}

/**
 * 后台验证表单
 *
 * @param unknown_type $field
 * @param unknown_type $title
 * @param unknown_type $type
 * @param unknown_type $arg
 * @return unknown
 */
function verify_field($field, $title, $type, $arg = '') {
  global $error_strs;

  $value = $_REQUEST[$field];

  switch ($type) {
    case "empty":
      if (trim($value) == "") {
        $error_strs[$field] = "内容为空";
        return false;
      }
      break;
    case "maxlength":
      if (!empty($value) && strlen($value) > $arg) {
        $error_strs[$field] = "最大可输入 $arg 个字符";
        return false;
      }
      break;
    case "minlength":
      if (!empty($value) && strlen($value) < $arg) {
        $error_strs[$field] = "最小可输入 $arg 个字符";
        return false;
      }
      break;
    case "number_only":
      if (!empty($value)  && !is_numeric(trim($value))) {
        $error_strs[$field] = "必须是数字";
        return false;
      }
      break;
    case "custom":
      if (!empty($value) && !preg_match($arg, trim($value))) {
        $error_strs[$field] = "格式错误";
        return false;
      }
      break;
    case "email":
      if (!empty($value) && !is_email($value)) {
        $error_strs[$field] = "email格式错误";
        return false;
      }
      break;
  }

  return true;
}

/**
 * 后台提示输入错误
 *
 * @param unknown_type $field
 * @return unknown
 */
function show_field_error($field) {
  global $error_strs;
  if ($error_strs[$field] != "") {
    return "<strong><span>".$error_strs[$field]."</span></strong>";
  }
}

/**
 * 递归删除目录
 *
 * @param unknown_type $directory
 * @param unknown_type $empty
 * @return unknown
 */
function recursive_remove_directory($directory, $empty = false) {
  if (substr($directory, -1) == '/') {
    $directory = substr($directory, 0, -1);
  }
  if (!file_exists($directory) || !is_dir($directory)) {
    return false;
  } elseif (is_readable($directory)) {
    $handle = opendir($directory);
    while (false !== ($item = readdir($handle))) {
      if ($item != '.' && $item != '..') {
        $path = $directory.'/'.$item;
        if (is_dir($path))  {
            recursive_remove_directory($path);
        } else {
            unlink($path);
        }
      }
    }
    closedir($handle);
    if ($empty == false) {
      if (!rmdir($directory)) {
          return false;
      }
    }
  }
  return true;
}

/**
 * 整理IP
 *
 * @return unknown
 */
function fetch_alt_ip() {
  $alt_ip = $_SERVER['REMOTE_ADDR'];

  if (isset($_SERVER['HTTP_CLIENT_IP'])) {
    $alt_ip = $_SERVER['HTTP_CLIENT_IP'];
  } else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
    // make sure we dont pick up an internal IP defined by RFC1918
    foreach ($matches[0] as $ip) {
      if (!preg_match("#^(10|172\.16|192\.168)\.#", $ip)) {
        $alt_ip = $ip;
        break;
      }
    }
  } else if (isset($_SERVER['HTTP_FROM'])) {
    $alt_ip = $_SERVER['HTTP_FROM'];
  }

  return $alt_ip;
}

/**
* Strips away [quote] tags and their contents from the specified string
*
* @param	string	Text to be stripped of quote tags
*
* @return	string
*/
function strip_quotes($text) {
	$lowertext = strtolower($text);

	// find all [quote tags
	$start_pos = array();
	$curpos = 0;
	do {
		$pos = strpos($lowertext, '[quote', $curpos);
		if ($pos !== false AND ($lowertext[$pos + 6] == '=' OR $lowertext[$pos + 6] == ']')) {
			$start_pos["$pos"] = 'start';
		}

		$curpos = $pos + 6;
	} while ($pos !== false);

	if (sizeof($start_pos) == 0) {
		return $text;
	}

	// find all [/quote] tags
	$end_pos = array();
	$curpos = 0;
	do {
		$pos = strpos($lowertext, '[/quote]', $curpos);
		if ($pos !== false) {
			$end_pos["$pos"] = 'end';
			$curpos = $pos + 8;
		}
	} while ($pos !== false);

	if (sizeof($end_pos) == 0) {
		return $text;
	}

	// merge them together and sort based on position in string
	$pos_list = $start_pos + $end_pos;
	ksort($pos_list);

	do {
		// build a stack that represents when a quote tag is opened
		// and add non-quote text to the new string
		$stack = array();
		$newtext = '';
		$substr_pos = 0;
		foreach ($pos_list as $pos => $type) {
			$stacksize = sizeof($stack);
			if ($type == 'start') {
				// empty stack, so add from the last close tag or the beginning of the string
				if ($stacksize == 0) {
					$newtext .= substr($text, $substr_pos, $pos - $substr_pos);
				}
				array_push($stack, $pos);
			} else {
				// pop off the latest opened tag
				if ($stacksize) {
					array_pop($stack);
					$substr_pos = $pos + 8;
				}
			}
		}

		// add any trailing text
		$newtext .= substr($text, $substr_pos);

		// check to see if there's a stack remaining, remove those points
		// as key points, and repeat. Allows emulation of a non-greedy-type
		// recursion.
		if ($stack) {
			foreach ($stack as $pos) {
				unset($pos_list["$pos"]);
			}
		}
	} while ($stack);

	return $newtext;
}

/**
* Strips away bbcode from a given string, leaving plain text
*
* @param	string	Text to be stripped of bbcode tags
* @param	boolean	If true, strip away quote tags AND their contents
* @param	boolean	If true, use the fast-and-dirty method rather than the shiny and nice method
*
* @return	string
*/
function strip_bbcode($message, $stripquotes = false, $fast_and_dirty = false, $showlinks = true) {
	$find = array();
	$replace = array();

	if ($stripquotes) {
		// [quote=username] and [quote]
		$message = strip_quotes($message);
	}

	// a really quick and rather nasty way of removing vbcode
	if ($fast_and_dirty) {
		// any old thing in square brackets
		$find[] = '#\[.*/?\]#siU';
		$replace[] = '';

		$message = preg_replace($find, $replace, $message);
	} else {
		// simple links
		$find[] = '#\[(email|url)=("??)(.+)\\2\]\\3\[/\\1\]#siU';
		$replace[] = '\3';

		// named links
		$find[] = '#\[(email|url)=("??)(.+)\\2\](.+)\[/\\1\]#siU';
		$replace[] = ($showlinks ? '\4 (\3)' : '\4');

		// replace links (and quotes if specified) from message
		$message = preg_replace($find, $replace, $message);

		// strip out all other instances of [x]...[/x]
		while(preg_match_all('#\[(\w+?)(?>[^\]]*?)\](.*)(\[/\1\])#siU', $message, $regs)) {
			foreach($regs[0] AS $key => $val) {
				$message  = str_replace($val, $regs[2]["$key"], $message);
			}
		}
		$message = str_replace('[*]', ' ', $message);
	}

	return trim($message);
}

function shortcut($string, $length) {
	if (advstrlen($string) > $length) {
		return trim(advchop($string, $length))."...";
	} else {
		return trim($string);
	}
}

/**
* Converts html entities to a regular character so strlen can be performed
*
* @param	string	String to be measured
*/
function advstrlen($string) {
	$string = preg_replace('#&\#([0-9]+);#', '_', $string);

	if (function_exists('mb_strlen') AND $length = @mb_strlen($string, 'utf-8')) {
		return $length;
	} else {
		return strlen($string);
	}
}

/**
* Chops off a string at a specific length, counting entities as once character
* and using multibyte-safe functions if available.
*
* @param  string  String to chop
* @param  integer Number of characters to chop at
*
* @return string  Chopped string
*/
function advchop($string, $length) {
  $length = intval($length);
  if ($length <= 0) {
    return $string;
  }

  if (preg_match_all('/&(#[0-9]+|lt|gt|quot|amp);/', $string, $matches, PREG_OFFSET_CAPTURE)) {
    // find all entities because we need to count them as 1 character
    foreach ($matches[0] AS $match) {
      $entity_length = strlen($match[0]);
      $offset = $match[1];

      // < since length starts at 1 but offset starts at 0
      if ($offset < $length) {
        // this entity happens in the chop area, so extend the length to include this
        // -1  since the entity should still count as 1 character
        $length += strlen($match[0])  - 1;
      } else {
        break;
      }
    }
  }

  if (function_exists('mb_substr') AND ($substr = @mb_substr($string, 0, $length, 'utf-8')) != '') {
    return $substr;
  } else{
    return substr($string, 0, $length);
  }
}

/**
 * 通用的翻页函数
 * 用于前台！
 */
function pagination($page, $length, $total, $link_template) {
  # 把url转换成标准的字符串，%s%才能替换
  $link_template = urldecode($link_template);

  # 张开的大小
  $available_pages = 4; // 必须为双数
  $start_page = 0;
  $stop_page = 0;

  # 总页数
  $total_pages = ceil($total / $length);
  if ($total_pages < 1) $total_pages = 1;
  $first_page = 1;

  if ($page < 1) $page = 1;
  if ($page > $total_pages) $page = $total_pages;

  if ($total_pages <= $available_pages + 4) {
    $start_page = 1;
    $stop_page = $total_pages;
  } else {
    $start_page = $page - ($available_pages / 2);
    if ($start_page < 4) {
      $start_page = 1;
    }
    if ($start_page > $total_pages - ($available_pages + 2)) {
      $start_page = $total_pages - ($available_pages + 2);
    }

    $stop_page = $start_page + $available_pages;
    if ($stop_page < $available_pages + 3) {
      $stop_page = $available_pages + 3;
    }
    if ($stop_page > $total_pages - 3) {
      $stop_page = $total_pages;
    }
  }

 // echo "<ul>";
  //echo "<li>Page $page of $total_pages</li>";

  # 上一页
  if ($page > $first_page) {
    $link = str_replace("%s%", ($page - 1), $link_template);
   // echo "<li><a href=\"$link\"><span class=\"prev\">Prev</span></a></li>";
    echo "<a href=\"{$link}\"> < </a>";
  }else{
   // echo "<li id=\"navprev\"><span class=\"disable\"><span class=\"prev\">Prev</span></span></li>";
    echo "<span class=\"disabled\"> < </span>";
  }

  # 前几页，如果当前页大于3
  if ($start_page > 3) {
    $link = str_replace("%s%", 1, $link_template);
   // echo "<li><a href=\"{$link}\">1</a></li>";
      echo "<a href=\"{$link}\">1</a>";
    $link = str_replace("%s%", 2, $link_template);
  //  echo "<li><a href=\"{$link}\">2</a></li>";
  //  echo "<li>...</li>";
       echo "<a href=\"{$link}\">2</a>";
       echo "...";
  }

  for ($i = $start_page; $i <= $stop_page; $i++) {
    $link = str_replace("%s%", $i, $link_template);
    if ($i == $page) {
     // echo "<li class=\"red\">$i</li> ";
        echo "<span class=\"current\">$i</span>";
    } else {
      //echo "<li><a href=\"{$link}\">$i</a></li>";
        echo "<a href=\"{$link}\">$i</a>";
    }
  }

  # 如果当前页加上2小于等于最多页
  if ($stop_page < $total_pages - 2) {
    //echo "<li>...</li>";
      echo "...";
    $link = str_replace("%s%", $total_pages - 1, $link_template);
   // echo "<li><a href=\"{$link}\">".($total_pages - 1)."</a></li>";
     echo "<a href=\"{$link}\">".($total_pages - 1)."</a>";
    $link = str_replace("%s%", $total_pages, $link_template);
   // echo "<li><a href=\"{$link}\">$total_pages</a></li>";
     echo "<a href=\"{$link}\">$total_pages</a>";
  }

  # 下一页
  if ($page < $total_pages) {
    $link = str_replace("%s%", ($page + 1), $link_template);
    //echo "<li><a href=\"{$link}\"><span class=\"next\">Next</span></a></li>";
    echo "<a href=\"{$link}\"> > </a>";
  } else {
    //echo "<li id=\"navnext\"><span class=\"disable\"><span class=\"next\">Next</span></span></li>";
    echo "<span class=\"disabled\"> > </span>";
  }
 // echo "</ul>";
}

function st($i) {
  switch(floor($i/10) % 10) {
    default:
      switch( $i % 10 ) {
        case 1: return 'st';
        case 2: return 'nd';
        case 3: return 'rd';
      }
    case 1:
  }
  return 'th';
}

/*
	Paul's Simple Diff Algorithm v 0.1
	(C) Paul Butler 2007 <http://www.paulbutler.org/>
	May be used and distributed under the zlib/libpng license.

	This code is intended for learning purposes; it was written with short
	code taking priority over performance. It could be used in a practical
	application, but there are a few ways it could be optimized.

	Given two arrays, the function diff will return an array of the changes.
	I won't describe the format of the array, but it will be obvious
	if you use print_r() on the result of a diff on some test data.

	htmlDiff is a wrapper for the diff command, it takes two strings and
	returns the differences in HTML. The tags used are <ins> and <del>,
	which can easily be styled with CSS.
*/

function diff($old, $new){
	foreach($old as $oindex => $ovalue){
		$nkeys = array_keys($new, $ovalue);
		foreach($nkeys as $nindex){
			$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
				$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
			if($matrix[$oindex][$nindex] > $maxlen){
				$maxlen = $matrix[$oindex][$nindex];
				$omax = $oindex + 1 - $maxlen;
				$nmax = $nindex + 1 - $maxlen;
			}
		}
	}
	if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
	return array_merge(
		diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
		array_slice($new, $nmax, $maxlen),
		diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

function htmlDiff($old, $new){
	$diff = diff(explode(' ', $old), explode(' ', $new));
	foreach($diff as $k){
		if(is_array($k))
			$ret .= (!empty($k['d'])?"<del>".implode(' ',$k['d'])."</del> ":'').
				(!empty($k['i'])?"<ins>".implode(' ',$k['i'])."</ins> ":'');
		else $ret .= $k . ' ';
	}
	return $ret;
}

function is_email ($email, $checkDNS = false) {
        //      Check that $email is a valid address
        //              (http://tools.ietf.org/html/rfc3696)
        //              (http://tools.ietf.org/html/rfc2822)
        //              (http://tools.ietf.org/html/rfc5322#section-3.4.1)
        //              (http://tools.ietf.org/html/rfc5321#section-4.1.3)
        //              (http://tools.ietf.org/html/rfc4291#section-2.2)
        //              (http://tools.ietf.org/html/rfc1123#section-2.1)

        //      the upper limit on address lengths should normally be considered to be 256
        //              (http://www.rfc-editor.org/errata_search.php?rfc=3696)
        if (strlen($email) > 256)       return false;   //      Too long

        //      Contemporary email addresses consist of a "local part" separated from
        //      a "domain part" (a fully-qualified domain name) by an at-sign ("@").
        //              (http://tools.ietf.org/html/rfc3696#section-3)
        $index = strrpos($email,'@');

        if ($index === false)           return false;   //      No at-sign
        if ($index === 0)                       return false;   //      No local part
        if ($index > 64)                        return false;   //      Local part too long

        $localPart              = substr($email, 0, $index);
        $domain                 = substr($email, $index + 1);
        $domainLength   = strlen($domain);

        if ($domainLength === 0)        return false;   //      No domain part
        if ($domainLength > 255)        return false;   //      Domain part too long

        //      Let's check the local part for RFC compliance...
        //
        //      Any ASCII graphic (printing) character other than the
        //      at-sign ("@"), backslash, double quote, comma, or square brackets may
        //      appear without quoting.  If any of that list of excluded characters
        //      are to appear, they must be quoted
        //              (http://tools.ietf.org/html/rfc3696#section-3)
        if (preg_match('/^"(?:.)*"$/', $localPart) > 0) {
                //      Quoted-string tests:
                //
                //      Note that since quoted-pair
                //      is allowed in a quoted-string, the quote and backslash characters may
                //      appear in a quoted-string so long as they appear as a quoted-pair.
                //              (http://tools.ietf.org/html/rfc2822#section-3.2.5)
                $groupCount     = preg_match_all('/(?:^"|"$|\\\\\\\\|\\\\")|(\\\\|")/', $localPart, $matches);
                array_multisort($matches[1], SORT_DESC);
                if ($matches[1][0] !== '')                                                                              return false;   //      Unescaped quote or backslash character inside quoted string
                if (preg_match('/^"\\\\*"$/', $localPart) > 0)                                  return false;   //      "" and "\" are slipping through - must tidy this up
        } else {
                //      Unquoted string tests:
                //
                //      Period (".") may...appear, but may not be used to start or end the
                //      local part, nor may two or more consecutive periods appear.
                //              (http://tools.ietf.org/html/rfc3696#section-3)
                if (preg_match('/^\\.|\\.\\.|\\.$/', $localPart) > 0)                   return false;   //      Dots in wrong place

                //      Any excluded characters? i.e. <space>, @, [, ], \, ", <comma>
                if (preg_match('/[ @\\[\\]\\\\",]/', $localPart) > 0)
                        //      Check all excluded characters are escaped
                        $stripped = preg_replace('/\\\\[ @\\[\\]\\\\",]/', '', $localPart);
                        if (preg_match('/[ @\\[\\]\\\\",]/', $stripped) > 0)            return false;   //      Unquoted excluded characters
        }

        //      Now let's check the domain part...

        //      The domain name can also be replaced by an IP address in square brackets
        //              (http://tools.ietf.org/html/rfc3696#section-3)
        //              (http://tools.ietf.org/html/rfc5321#section-4.1.3)
        //              (http://tools.ietf.org/html/rfc4291#section-2.2)
        if (preg_match('/^\\[(.)+]$/', $domain) === 1) {
                //      It's an address-literal
                $addressLiteral = substr($domain, 1, $domainLength - 2);
                $matchesIP              = array();

                //      Extract IPv4 part from the end of the address-literal (if there is one)
                if (preg_match('/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $addressLiteral, $matchesIP) > 0) {
                        $index = strrpos($addressLiteral, $matchesIP[0]);

                        if ($index === 0) {
                                //      Nothing there except a valid IPv4 address, so...
                                return true;
                        } else {
                                //      Assume it's an attempt at a mixed address (IPv6 + IPv4)
                                if ($addressLiteral[$index - 1] !== ':')                        return false;   //      Character preceding IPv4 address must be ':'
                                if (substr($addressLiteral, 0, 5) !== 'IPv6:')          return false;   //      RFC5321 section 4.1.3

                                $IPv6 = substr($addressLiteral, 5, ($index ===7) ? 2 : $index - 6);
                                $groupMax = 6;
                        }
                } else {
                        //      It must be an attempt at pure IPv6
                        if (substr($addressLiteral, 0, 5) !== 'IPv6:')                  return false;   //      RFC5321 section 4.1.3
                        $IPv6 = substr($addressLiteral, 5);
                        $groupMax = 8;
                }

                $groupCount     = preg_match_all('/^[0-9a-fA-F]{0,4}|\\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $matchesIP);
                $index          = strpos($IPv6,'::');

                if ($index === false) {
                        //      We need exactly the right number of groups
                        if ($groupCount !== $groupMax)                                                  return false;   //      RFC5321 section 4.1.3
                } else {
                        if ($index !== strrpos($IPv6,'::'))                                             return false;   //      More than one '::'
                        $groupMax = ($index === 0 || $index === (strlen($IPv6) - 2)) ? $groupMax : $groupMax - 1;
                        if ($groupCount > $groupMax)                                                    return false;   //      Too many IPv6 groups in address
                }

                //      Check for unmatched characters
                array_multisort($matchesIP
[1], SORT_DESC);
                if ($matchesIP[1][0] !== '')                                                            return false;   //      Illegal characters in address

                //      It's a valid IPv6 address, so...
                return true;
        } else {
                //      It's a domain name...

                //      The syntax of a legal Internet host name was specified in RFC-952
                //      One aspect of host name syntax is hereby changed: the
                //      restriction on the first character is relaxed to allow either a
                //      letter or a digit.
                //              (http://tools.ietf.org/html/rfc1123#section-2.1)
                //
                //      NB RFC 1123 updates RFC 1035, but this is not currently apparent from reading RFC 1035.
                //
                //      Most common applications, including email and the Web, will generally not permit...escaped strings
                //              (http://tools.ietf.org/html/rfc3696#section-2)
                //
                //      Characters outside the set of alphabetic characters, digits, and hyphen MUST NOT appear in domain name
                //      labels for SMTP clients or servers
                //              (http://tools.ietf.org/html/rfc5321#section-4.1.2)
                //
                //      RFC5321 precludes the use of a trailing dot in a domain name for SMTP purposes
                //              (http://tools.ietf.org/html/rfc5321#section-4.1.2)
                $matches        = array();
                $groupCount     = preg_match_all('/(?:[0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z]|[a-zA-Z])(?:\\.|$)|(.)/', $domain, $matches);
                $level          = count($matches[0]);

                if ($level == 1)                                                                                        return false;   //      Mail host can't be a TLD

                $TLD = $matches[0][$level - 1];
                if (substr($TLD, strlen($TLD) - 1, 1) === '.')                          return false;   //      TLD can't end in a dot
                if (preg_match('/^[0-9]+$/', $TLD) > 0)                                         return false;   //      TLD can't be all-numeric

                //      Check for unmatched characters
                array_multisort($matches[1], SORT_DESC);
                if ($matches[1][0] !== '')                                                                      return false;   //      Illegal characters in domain, or label longer than 63 characters

                //      Check DNS?
                if ($checkDNS && function_exists('checkdnsrr')) {
                        if (!(checkdnsrr($domain, 'A') || checkdnsrr($domain, 'MX'))) {
                                                                                                                                        return false;   //      Domain doesn't actually exist
                        }
                }

                //      Eliminate all other factors, and the one which remains must be the truth.
                //              (Sherlock Holmes, The Sign of Four)
                return true;
        }
}

function get_ext($file)
{
    $arr = explode('.',$file);
    return strtolower(end($arr));
}

function download_file($archivo,$downloadfilename=NULL)
{
    if(file_exists($archivo)){
        $downloadfilename=$downloadfilename!==NULL ?
                 $downloadfilename : basename($archivo);
        header('Content-Description:File Transfer');
        header('Content-type:application/octet-stream');
        header('Content-Disposition:attachment;filename='.
                $downloadfilename);
        header('Content-Transfer-Encoding:binary');
        header('Expires:0');
        header('Cache-Control:must-revalidate,post-check=0,
                pre-check=0');
        header('Pragma:public');
        header('Content-Length:'.filesize($archivo));
        ob_clean();
        flush();
        readfile($archivo);
        exit;
    }
}

function download($file_dir,$file_name)
//参数说明：
//file_dir:文件所在目录
//file_name:文件名
{
  $file_dir = chop($file_dir);//去掉路径中多余的空格
  //得出要下载的文件的路径
  if($file_dir != '')
  {
    $file_path = $file_dir;
    if(substr($file_dir,strlen($file_dir)-1,strlen($file_dir)) != '/')
    $file_path .= '/';
    $file_path .= $file_name;
  } else {
    $file_path = $file_name;
  }
 
  //判断要下载的文件是否存在
  if(!file_exists($file_path))
  {
    echo '对不起,你要下载的文件不存在。';
    return false;
  }
 
  $file_size = filesize($file_path);
 
  header("Content-type: application/octet- tream");
  header("Accept-Range : byte ");
  header("Accept-Length: $file_size");
  header("Content-Disposition: attachment; filename=".$file_name);
 
  $fp= fopen($file_path,"r");
  $buffer_size = 1024;
  $cur_pos = 0;
 
  while(!feof($fp)&&$file_size-$cur_pos>$buffer_size)
  {
    $buffer = fread($fp,$buffer_size);
    echo $buffer;
    $cur_pos += $buffer_size;
  }
 
  $buffer = fread($fp,$file_size-$cur_pos);
  echo $buffer;
  fclose($fp);
  return true;
}
?>